package com.inspur.edp.common.expr.visitor.field;

import com.inspur.edp.common.expr.ast.ASTContext;
import com.inspur.edp.common.expr.ast.CompileUnitParser;
import com.inspur.edp.common.expr.ast.CompileUnitVisitor;
import com.inspur.edp.common.expr.parser.ExpressAstParser;
import com.inspur.edp.common.expr.spi.FieldVisitor;
import com.inspur.edp.common.expr.visitor.VisitResult;
import com.inspur.edp.common.type.Field;
import com.inspur.edp.common.type.Type;
import com.inspur.edp.common.type.TypeRefer;
import com.inspur.edp.common.type.parser.TypeParser;


/**
 * @author lizhaorui
 * @description TODO
 * @date 2024/7/15 18:48
 */
public class GetSetFieldVisitor implements FieldVisitor {

    public String getKind() {
        return Field.GET_SET_VALUE;
    }

    @Override
    public VisitResult visitGetter(CompileUnitVisitor visitor,
                                   ASTContext context,
                                   CompileUnitParser.FieldAccessExprContext fieldAccessExprContext,
                                   CompileUnitParser.ExpressContext objectExpr, Field field) {
        TypeRefer objectType = ExpressAstParser.getOriginalType(objectExpr, context);
        Type dslType = context.getType(objectType);
        String methodName = field.getGetter();
        if (methodName == null) {
            TypeRefer fieldTypeRefer = TypeParser.getFieldType(objectType, field.getCode());
            methodName = getDefaultGetMethod(fieldTypeRefer, field.getCode());
        }
        String objectExprDsl = visitor.visitExpress(objectExpr).toString();
        Object tagValue = objectExpr.getTag(FieldVisitor.CLASS_CAST_TAG_KEY);
        if (tagValue != null) {
            objectExprDsl = "(" + objectExprDsl + ")";
        }
        return new VisitResult(String.format("%s.%s()", objectExprDsl, methodName));
    }

    @Override
    public VisitResult visitSetter(CompileUnitVisitor visitor, ASTContext context, CompileUnitParser.ExpressContext objectExpr, Field field, CompileUnitParser.ExpressContext valueExpr) {
        TypeRefer objectType = ExpressAstParser.getOriginalType(objectExpr, context);
        Type dslType = context.getType(objectType);
        String setterMethodName = field.getSetter();
        if (setterMethodName == null) {
            setterMethodName = String.format("set" + firstCharToUpper(field.getCode()));
        }
        String objectExprDsl = visitor.visitExpress(objectExpr).toString();
        Object tagValue = objectExpr.getTag(FieldVisitor.CLASS_CAST_TAG_KEY);
        if (tagValue != null) {
            objectExprDsl = "(" + objectExprDsl + ")";
        }
        String valueExprDsl = visitor.visitExpress(valueExpr).toString();
        return new VisitResult(String.format("%s.%s(%s)", objectExprDsl, setterMethodName, valueExprDsl));
    }

    private String getDefaultGetMethod(TypeRefer fieldTypeRefer, String fieldName) {
        if (fieldTypeRefer.getTypeId().equalsIgnoreCase("boolean")) {
            return "is" + firstCharToUpper(fieldName);
        } else {
            return "get" + firstCharToUpper(fieldName);
        }
    }

    private String firstCharToUpper(String fieldName) {
        String firstC = fieldName.substring(0, 1);
        return firstC.toUpperCase() + fieldName.substring(1);
    }

}
